#include "StdAfx.h"
#include "FullScreenPostProcess.h"
#include "RenderContext.h"
#include "GraphCamera.h"
#include "Level.h"

//---------------------------
// Constructor & Destructor
//---------------------------
FullScreenPostProcess::FullScreenPostProcess(const tstring& TexFileName, Level* level):
	m_NumVertices(0)
	,m_NumIndices(0)
	,m_VertexBufferStride(0)
	,m_pTextureMapVariabele(0)
	,m_pTextureRV(0)
	,m_pVertexLayout(0)
	,m_pVertexBuffer(0)
	,m_pIndexBuffer(0)
	,m_pEffect(0)
	,m_pDefaultTechnique(0)
	,m_pLevel(level)
	,m_pContentManager(0)
	,m_TextureName(TexFileName)
{
	// nothing to create
}

FullScreenPostProcess::~FullScreenPostProcess()
{
	// nothing to destroFullScreenPostProcess
}
void FullScreenPostProcess::Initialize(ContentManager *pContentManager)
{
	m_pContentManager = pContentManager;
	CreateEffect(_T("./Effect/Grayscale.fx"));
	DefineInputlayout();
	FillVertexAndIndexBuffer();

}
void FullScreenPostProcess::Draw()const
{

}
void FullScreenPostProcess::Draw(const RenderContext* pRenderContext)
{
	if(!m_pDefaultTechnique )
	{
		MessageBox(0,_T("No Technique"),_T("ERROR"),0);
		return;
	}
	if(!m_pVertexBuffer)
	{
		MessageBox(0,_T("No Vertices"),_T("ERROR"),0);
		return;
	}	

	// Update Shader matrix variables
	D3DXMATRIX matView = pRenderContext->GetCamera()->GetView();
	D3DXMATRIX matProj = pRenderContext->GetCamera()->GetProj();

	// Set the input layout
    m_pLevel->GetDevice()->IASetInputLayout( m_pVertexLayout );

    // Set vertex buffer(s)
    UINT offset = 0;
    m_pLevel->GetDevice()->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &m_VertexBufferStride, &offset );
   	
	// Set index buffer
	m_pLevel->GetDevice()->IASetIndexBuffer(m_pIndexBuffer,DXGI_FORMAT_R32_UINT,0);

    // Set primitive topology
    m_pLevel->GetDevice()->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

    D3D10_TECHNIQUE_DESC techDesc;
    m_pDefaultTechnique->GetDesc( &techDesc );
    for( UINT p = 0; p < techDesc.Passes; ++p )
    {
        m_pDefaultTechnique->GetPassByIndex(p)->Apply(0);
		m_pLevel->GetDevice()->DrawIndexed( m_NumIndices, 0, 0 ); 
    }
}
void FullScreenPostProcess::BuildStacks(vector<VertexPosTex>& vertices, vector<DWORD>& indices)
{
	//TODO initialize 4 vertices to form a square, choose position and color
	VertexPosTex v1(-1,-1,0,0,1);//left bottom
	vertices.push_back(v1);
	VertexPosTex v2(-1,1,0,0,0);//left top
	vertices.push_back(v2);
	VertexPosTex v3(1,1,0,1,0);//righttop
	vertices.push_back(v3);
	VertexPosTex v4(1,-1,0,1,1);//right bottom
	vertices.push_back(v4);

	//TODO add two triangle (backface culling!)
	indices.push_back(0);
	indices.push_back(1);
	indices.push_back(2);

	indices.push_back(2);
	indices.push_back(3);
	indices.push_back(0);

	m_NumIndices = indices.size();
	m_NumVertices = vertices.size();
}
void FullScreenPostProcess::FillVertexAndIndexBuffer()
{
	vector<VertexPosTex> vertices;
	vector<DWORD> indices;

	//De quad aanmaken
	BuildStacks(vertices, indices);
	
	D3D10_BUFFER_DESC vbd;
    vbd.Usage = D3D10_USAGE_IMMUTABLE;
    vbd.ByteWidth = sizeof(VertexPosNormTex) * (UINT)vertices.size();
    vbd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
    vbd.CPUAccessFlags = 0;
    vbd.MiscFlags = 0;
	D3D10_SUBRESOURCE_DATA vinitData;
    vinitData.pSysMem = &vertices[0];
    HR(m_pLevel->GetDevice()->CreateBuffer(&vbd, &vinitData, &m_pVertexBuffer));

	D3D10_BUFFER_DESC ibd;
    ibd.Usage = D3D10_USAGE_IMMUTABLE;
    ibd.ByteWidth = sizeof(DWORD) * indices.size();
    ibd.BindFlags = D3D10_BIND_INDEX_BUFFER;
    ibd.CPUAccessFlags = 0;
    ibd.MiscFlags = 0;
    D3D10_SUBRESOURCE_DATA initData;
    initData.pSysMem = &indices[0];
    HR(m_pLevel->GetDevice()->CreateBuffer(&ibd, &initData, &m_pIndexBuffer));

	m_NumIndices = (UINT)indices.size();
}

void FullScreenPostProcess::GetEffectVariables()
{
	m_pTextureMapVariabele = m_pEffect->GetVariableByName( "gTexture" )->AsShaderResource();
	if(!m_pTextureMapVariabele->IsValid())MessageBox(0,_T("Getting EffectSemantic DiffuseMap Failed"),_T("ERROR"),0);
}
void FullScreenPostProcess::DefineInputlayout()
{
	 // Define the input layout
    D3D10_INPUT_ELEMENT_DESC layout[] =
    {
		{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
		{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
    };
    UINT numElements = sizeof(layout)/sizeof(layout[0]);

    // Create the input layout
    D3D10_PASS_DESC PassDesc;
	// Get the pass decriptor from the effect technique
    HR(m_pDefaultTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc ));
    HR(m_pLevel->GetDevice()->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &m_pVertexLayout ));

	//important set the size of the vertexbuffer, is used in draw base member function
	m_VertexBufferStride = sizeof(VertexPosTex);
}
void FullScreenPostProcess::UpdateEffectVariables()const
{
	m_pTextureMapVariabele->SetResource(m_pTextureRV);
}
void FullScreenPostProcess::LoadTexture(const tstring& TexFileName)
{
	m_pTextureRV = m_pContentManager->GetTexture(m_pLevel->GetDevice(),TexFileName);
}
// Loads and compiles the effect and gets the technique
void FullScreenPostProcess::CreateEffect(const tstring& EffectFilename)
{
	m_pEffect = m_pContentManager->GetEffect(m_pLevel->GetDevice(),EffectFilename);
	
	//get first technique found
	m_pDefaultTechnique = m_pEffect->GetTechniqueByIndex(0);
	if(!m_pDefaultTechnique->IsValid())MessageBox(0,_T("Technique not valid"),_T("ERROR"),0);

	GetEffectVariables();
}
//---------------------------
// Eigen methoden
//---------------------------

// vul aan met je eigen methoden.


